// servicesession
package serviceclient

import (
	"io"
	"swim/etc"
	"swim/request"
	"swim/util/nuid"
	"sync"
	"time"
)

type ServiceSessionPool struct {
	sync.Mutex
	SessionPool map[string]*ServiceSesion
	MaxClients  int
}

func NewSessionPool() *ServiceSessionPool {
	sPool := new(ServiceSessionPool)
	sPool.SessionPool = make(map[string]*ServiceSesion)
	sPool.MaxClients = 0
	return sPool
}

//添加服务人员的会话
//iType为面向对方人员的对话类别
func (g *ServiceSessionPool) AddSession(sc *ServiceClient, iType int, w io.Writer,
	RemoteAddr string) *ServiceSesion {
	if g.MaxClients > 0 && len(g.SessionPool) > g.MaxClients {
		return nil
	}
	g.Lock()
	s := new(ServiceSesion)
	s.MsgPool = make(chan request.WebMsg, etc.S_MAX_MSG_POOL_SIZE)
	s.CType = iType
	s.Sid = nuid.Next()
	s.SesionTickCount = time.Now()
	s.wr = w
	s.IP = RemoteAddr
	s.UserService = sc
	g.SessionPool[s.Sid] = s
	g.Unlock()

	return s
}
func (g *ServiceSessionPool) RemoveSession(sid string) bool {
	c := g.SessionPool[sid]
	if c == nil {
		return false
	}
	//c.On_Logout()
	close(c.MsgPool)
	c.DelMsgKey()
	g.Lock()
	delete(g.SessionPool, sid)
	g.Unlock()
	return true
}
func (g *ServiceSessionPool) FindSessionBySid(sid string) (*ServiceSesion, bool) {
	c := g.SessionPool[sid]
	if c == nil {
		return nil, false
	}
	return c, true
}

func (g *ServiceSessionPool) RemoveSessionByAccount(account string) {

	for _, session := range g.SessionPool {
		if session.UserService.User.Account == account {
			session.DelMsgKey()
			close(session.MsgPool)
			g.Lock()
			delete(g.SessionPool, session.Sid)
			g.Unlock()
		}
	}
	return
}

//清除过期过期用户
func (g *ServiceSessionPool) StartGC() {
	go g.vaccuum()
}

//check timeout
func (g *ServiceSessionPool) vaccuum() {

	for {
		<-time.After(etc.S_GC_SESSION_TIME * time.Second)
		if g.SessionPool == nil {
			return
		}
		for sid := range g.SessionPool {
			g.itemExpired(sid)
		}
	}

	return
}
func (g *ServiceSessionPool) itemExpired(sid string) bool {

	itm, ok := g.SessionPool[sid]
	if !ok {
		return true
	}
	if itm.isExpire() {
		itm.UserService.RemoveServiceSession(sid)
		g.RemoveSession(sid)
		return true
	}
	return false
}
